//
//  YYCollectionViewLayout.swift
//  CodeLibrary_Swift
//
//  Created by 陆文宇 on 2017/2/4.
//  Copyright © 2017年 陆文宇. All rights reserved.
//

import UIKit

class YYCollectionViewTransverseFlowLayout: UICollectionViewLayout {
    
    var headerReferenceSize: CGSize = .zero
    var footererReferenceSize: CGSize = .zero
    var lineHeight: CGFloat = 20
    /// 瀑布流的列间距
    var lineSpacing: CGFloat = 8
    /// 瀑布流的行间距
    var interitemSpacing: CGFloat = 8
    /// 分区间隔
    var sectionInsets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
    /**
     *  动态求宽度的Closure
     *      Parameter height:    高度
     *      Parameter indexPath: 坐标
     */
    var widthOfItem: (CGFloat, IndexPath) -> CGFloat = { (_, _) in
        return 100
    }
    
    private lazy var attributes: Array<UICollectionViewLayoutAttributes> = []
    private lazy var itemWidths: Array<CGFloat> = []
    private lazy var totalHeight: CGFloat = 0
    
    override func prepare() {
        super.prepare()
        
        attributes.removeAll()
        totalHeight = 0
        
        for i in 0 ..< collectionView!.numberOfSections {
            itemWidths.removeAll()
            totalHeight += i == 0 ? sectionInsets.top : sectionInsets.bottom + sectionInsets.top
            
            let supplementaryHeaderViewAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, with: IndexPath(item: 0, section: i))
            supplementaryHeaderViewAttributes.frame = CGRect(x: 0, y: totalHeight, width: collectionView!.yy_width, height: headerReferenceSize.height)
            attributes.append(supplementaryHeaderViewAttributes)
            totalHeight += headerReferenceSize.height
            
            let numberOfItems: Int = collectionView!.numberOfItems(inSection: i)
            for j in 0 ..< numberOfItems {
                let indexPath: IndexPath = IndexPath(item: j, section: i)
                let itemWidth: CGFloat = widthOfItem(lineHeight, indexPath)
                
                let attribute: UICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                var x: CGFloat = sectionInsets.left
                if let last = itemWidths.last {
                    if collectionView!.yy_width - sectionInsets.right - last > itemWidth {
                        x = last
                        itemWidths[itemWidths.count - 1] += itemWidth + lineSpacing
                    } else {
                        itemWidths.append(x + itemWidth + lineSpacing)
                        totalHeight += lineHeight + interitemSpacing
                    }
                } else {
                    itemWidths.append(x + itemWidth + lineSpacing)
                }
                let y: CGFloat = totalHeight
                let width: CGFloat = itemWidth
                let height: CGFloat = lineHeight
                attribute.frame = CGRect(x: x, y: y, width: width, height: height)
                attributes.append(attribute)
            }
            
            totalHeight += lineHeight
            
            let supplementaryFooterViewAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, with: IndexPath(item: 0, section: i))
            supplementaryFooterViewAttributes.frame = CGRect(x: 0, y: totalHeight, width: collectionView!.yy_width, height: footererReferenceSize.height)
            attributes.append(supplementaryFooterViewAttributes)
            totalHeight += footererReferenceSize.height
        }
    }
    
    override var collectionViewContentSize: CGSize {
        var size: CGSize = collectionView!.frame.size
        size.height = totalHeight + lineHeight + sectionInsets.bottom
        return size
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attributes
    }
    
}

class YYCollectionViewCascadeFlowLayout: UICollectionViewLayout {
    
    var headerReferenceSize: CGSize = .zero
    var footererReferenceSize: CGSize = .zero
    /// 瀑布流的列数
    var numberOfColumns: Int = 2
    /// 瀑布流的列间距
    var lineSpacing: CGFloat = 8
    /// 瀑布流的行间距
    var interitemSpacing: CGFloat = 8
    /// 分区间隔
    var sectionInsets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
    /**
     *  动态求高度的Closure
     *      Parameter width:     宽度
     *      Parameter indexPath: 坐标
     */
    var heightOfItem: (CGFloat, IndexPath) -> CGFloat = { (_, _) in
        return 100
    }
    
    private lazy var attributes: Array<UICollectionViewLayoutAttributes> = []
    private lazy var heights: Array<CGFloat> = []
    
    
    override func prepare() {
        super.prepare()
        
        attributes.removeAll()
        
        let itemWidth: CGFloat = (collectionView!.frame.size.width - lineSpacing * CGFloat(numberOfColumns - 1) - sectionInsets.left - sectionInsets.right) / CGFloat(numberOfColumns)
        for i in 0 ..< collectionView!.numberOfSections {
            let height = (heights.max() ?? interitemSpacing - sectionInsets.bottom) - interitemSpacing + sectionInsets.bottom + sectionInsets.top
            heights.removeAll()
            for _ in 0 ..< numberOfColumns {
                heights.append(height + headerReferenceSize.height + footererReferenceSize.height)
            }
            
            let supplementaryHeaderViewAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, with: IndexPath(item: 0, section: i))
            supplementaryHeaderViewAttributes.frame = CGRect(x: 0, y: height, width: collectionView!.yy_width, height: headerReferenceSize.height)
            attributes.append(supplementaryHeaderViewAttributes)
            
            let numberOfItems: Int = collectionView!.numberOfItems(inSection: i)
            for j in 0 ..< numberOfItems {
                let indexPath: IndexPath = IndexPath(item: j, section: i)
                let itemHeight: CGFloat = heightOfItem(itemWidth, indexPath)
                let shortestIndex: Int = heights.index(of: heights.min()!)!
                
                let attribute: UICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                let x: CGFloat = sectionInsets.left + (itemWidth + lineSpacing) * CGFloat(shortestIndex)
                let y: CGFloat = heights[shortestIndex]
                let width: CGFloat = itemWidth
                let height: CGFloat = itemHeight
                attribute.frame = CGRect(x: x, y: y, width: width, height: height)
                attributes.append(attribute)
                
                let newHeight: CGFloat = heights[shortestIndex] + itemHeight + interitemSpacing
                heights[shortestIndex] = newHeight
            }
            
            let supplementaryFooterViewAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, with: IndexPath(item: 0, section: i))
            supplementaryFooterViewAttributes.frame = CGRect(x: 0, y: heights.max()! - interitemSpacing, width: collectionView!.yy_width, height: footererReferenceSize.height)
            attributes.append(supplementaryFooterViewAttributes)
        }
    }
    
    override var collectionViewContentSize: CGSize {
        var size: CGSize = collectionView!.frame.size
        size.height = heights.max()! - interitemSpacing + sectionInsets.bottom
        return size
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attributes
    }
    
}
